import { errors } from "./errors";
import type { PermissionType } from "./type";

/**
 * 本地存储
 * @param key
 * @param val
 * @returns
 */
export function setStorage(key: string, val: string) {
  return window.localStorage.setItem(key, val);
}

/**
 * 本地获取
 * @param key
 * @returns
 */
export function getStorage(key: string) {
  return window.localStorage.getItem(key);
}

// 判断是不是引用类型
function isComplexType(key: any) {
  return key !== null && (typeof key === "object" || typeof key === "function");
}

/**
 * 深拷贝
 * @param obj
 * @param hash
 * @returns
 */
export function deepClone(obj: any, hash = new WeakMap()) {
  // 日期对象直接返回一个新的日期对象
  if (obj.constructor === Date) return new Date(obj);

  //正则对象直接返回一个新的正则对象
  if (obj.constructor === RegExp) return new RegExp(obj);

  //如果循环引用了就用 weakMap 来解决; WeakMap带有垃圾回收
  if (hash.has(obj)) return hash.get(obj);

  // 获取一个对象的所有自身属性的描述符
  const allDesc = Object.getOwnPropertyDescriptors(obj);

  //遍历传入参数所有键的特性
  const cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc);

  //继承原型链
  hash.set(obj, cloneObj);

  for (const key of Reflect.ownKeys(obj)) {
    cloneObj[key] =
      isComplexType(obj[key]) && typeof obj[key] !== "function"
        ? deepClone(obj[key], hash)
        : obj[key];
  }
  return cloneObj;
}

// 加法
export function add(num: number) {
  return ++num;
}

// 减法
export function reduce(num: number) {
  return --num;
}

// 获取随机六位数组合
export function randomNo(len?: number) {
  if (!len) len = 6;
  let userNo = "";
  for (let i = 0; i < len; i++) {
    const randomNum = Math.random() * 10;
    const no = Math.floor(randomNum);
    userNo = `${userNo}${no}`;
  }
  return userNo;
}

/**
 * 请求错误处理
 * @param statusCode
 * @returns
 */
export function handleErrors(statusCode: number) {
  if (!statusCode) return;
  throw new Error(errors[statusCode].msg);
}

// 判断权限
export function hasPermission(permissions: PermissionType[], subject: string) {
  return permissions && permissions.length
    ? permissions.find((p: PermissionType) => p.subject === subject)
    : null;
}
